package com.tvunetworks.center.device.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.tvunetworks.center.common.conf.properties.AccessProperties;
import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.common.model.CommandParam;
import com.tvunetworks.center.common.model.ExtendExternal;
import com.tvunetworks.center.common.model.dto.grid.AcceptedGrid;
import com.tvunetworks.center.common.model.param.AccessParam;
import com.tvunetworks.center.common.model.param.GridStartLiveParam;
import com.tvunetworks.center.common.model.param.GridStopLiveParam;
import com.tvunetworks.center.common.util.*;
import com.tvunetworks.center.device.constant.CommandConstant;
import com.tvunetworks.center.device.mapper.ExtendExternalMapper;
import com.tvunetworks.center.device.mapper.ExternalReceiverRelationMapper;
import com.tvunetworks.center.device.mapper.MyDeviceMapper;
import com.tvunetworks.center.device.mapper.UserDeviceMapper;
import com.tvunetworks.center.device.model.ExternalReceiverRelation;
import com.tvunetworks.center.device.model.dto.BelongUserResult;
import com.tvunetworks.center.device.model.json.SetBitrateAndDelayParam;
import com.tvunetworks.center.device.model.param.*;
import com.tvunetworks.center.device.model.result.ResultConstant;
import com.tvunetworks.center.device.service.DeviceService;
import com.tvunetworks.center.device.service.ExtService;
import com.tvunetworks.center.device.service.ReceiverControlService;
import com.tvunetworks.center.device.service.feign.*;
import com.tvunetworks.center.device.util.DistributedGlobalIdUtil;
import com.tvunetworks.center.device.util.RCommandDataUtil;
import com.tvunetworks.center.device.util.ReceiverResultUtil;
import com.tvunetworks.center.gs.model.Device;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: tvucc-device
 * @description: ReceiverControlServiceImpl
 * @author lebronchen
 * @create: 2019-03-15 13:22
 **/
@Service
@Slf4j
@EnableConfigurationProperties(AccessProperties.class)
public class ReceiverControlServiceImpl implements ReceiverControlService  {

    @Autowired
    private RwsFeignService rwsFeignService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private AccessFeignService accessFeignService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DevicePairService devicePairService;
    @Autowired
    private TokenFeignService tokenFeignService;
    @Autowired
    private ExtService extService;
    @Autowired
    private MyDeviceMapper myDeviceMapper;
    @Autowired
    private TvuSearchFeignService tvuSearchFeignService;

    @Autowired
    private GridFeignService gridFeignService;
    @Autowired
    private UserFeignService userFeignService;

    @Autowired
    private AccessProperties accessProperties;


    @Autowired
    private UserDeviceMapper userDeviceMapper;
    @Autowired
    private ExtendExternalMapper extendExternalMapper;
    @Autowired
    private DistributedGlobalIdUtil distributedGlobalIdUtil;
    @Autowired
    private ExternalReceiverRelationMapper externalReceiverRelationMapper;

    @Value("${ext.type}")
    private String extType;
    @Value("${liveCheckDeviceOfflineTime}")
    private long liveCheckDeviceOfflineTime;
    @Value("${enableCustomizedCC}")
    private boolean enableCustomizedCC;
    @Value("${partylineTokenType:partyline}")
    private String partylineTokenType;
    @Value("${LinuxR.restart.version:7.7}")
    private double linuxRestartVersion;
    @Value("${update.slug.url:http://10.12.22.101//route-mma/tvu-search/public/v1/media/updateslug}")
    private String updateSlugUrl;
    @Value("${get.slug.url:http://10.12.22.101//route-mma/tvu-search/public/v1/media/newestSlugInfo}")
    private String getSlugUrl;


   /* @Value("${delete.slug.url:http://10.12.22.101//route-mma/tvu-search/public/v1/media/deleteslug}")
    private String deleteSlugUrl;*/

    // check 设备属于用户
    @Override
    public Result<String> startLive(String userId, String userRole, String rid, String sourceId) {
        // 只有普通用户才判断
        if(StringUtils.equals(userRole, LocalConstant.UserRole.USER)){
            // 检查是否有startLive权限
            // checkFeature方法没有校验admin默认拥有的方法  暂时不check startLive feature
            boolean allow = userFeignService.checkUserRole(userId, "startLive");
            if (!allow) {
                return ResultUtil.userRoleNoFeature();
            }
        }
        Device r = deviceService.getCurrentDevice(rid);
        Device source = deviceService.getCurrentDevice(sourceId);
        if (source == null) {
            //从webR中获取ext,查看是否存在,存在则直接startLive
            if (this.checkSourceExistInWebR(rid, sourceId)) {
                // 校验R  设备  是否存在，状态是否正确
                Result<String> checkStatus = this.startLiveCheckReceierStatus(r);
                if (!checkStatus.assertSuccess()) {
                    return checkStatus;
                }
                // 校验 R 是否存在 booking
                checkStatus = this.startLiveCheckBooking(rid);
                if (!checkStatus.assertSuccess()) {
                    return checkStatus;
                }
                return this.startLiveCommand(rid, sourceId);
            }
        }
        // 校验设备 是否存在，状态是否正确
        Result<String> checkStatus = this.startLiveCheckStatus(r, source);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        // 校验 R 是否存在 booking
        checkStatus = this.startLiveCheckBooking(rid);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        if (!enableCustomizedCC) {
            // 如果是正式 CC 校验 Source/R 是否属于用户  以及是否调用 Grid CC 直播
            BelongUserResult sourceBelongUser = this.sourceBelongUser(userId, source, rid);

            if (sourceBelongUser.getCode() == BelongUserResult.NOT_BELONG) {
                boolean isPartyLinePair = this.checkIsPartyLinePair(rid, sourceId);
                if (!isPartyLinePair) {
                    if (!this.checkSourceExistInWebR(rid, sourceId)) {
                        return ResultUtil.error("81100110", "Source not belong to user", sourceId);
                    }

                } else {
                    log.error("startLive check source not belong to user but is partyline pair, rid:[{}] sid:[{}]", rid, sourceId);
                }
            }

            BelongUserResult rBelongUser = this.receiverBelongUser(userId, r);

            if (rBelongUser.getCode() == BelongUserResult.NOT_BELONG) {
                return ResultUtil.error("81100111", "Receiver not belong to user", rid);
            }

            // 如果是从Grid 请求过来的还要看有没有配对过，
            // 如果之前有配对就不调 Grid 的 start Live
            // 如果之前没有配对就调
            if (sourceBelongUser.getCode() == BelongUserResult.GRID_BELONG) {

                try {
                    GridStartLiveParam param = new GridStartLiveParam()
                            .setRequestId((String) sourceBelongUser.getResult()) // 获取到的 request id
                            .setRId(rid)
                            .setXId(sourceId)
                            .setUserId(userId);

                    Result result = gridFeignService.gridStartLive(param);

                    if (StringUtils.equals(ResultUtil.SUCCESS, result.getErrorCode())) {
                        return ResultUtil.success();
                    } else {
                        return ResultUtil.error("81100114", result.getErrorInfo());
                    }

                } catch (Exception e) {
                    log.error("Grid start live failed :", e);
                    return ResultUtil.error("81100113", "Grid start live failed :" + e.getMessage());
                }
            }
        }

        // 下发 Ext 到 R
        startLiveDistributeExt(rid, source);

        return this.startLiveCommand(rid, sourceId);
    }

    private Result<String> startLiveCheckReceierStatus(Device r) {
        if (r == null) {
            return ResultUtil.error("81100101", "Receiver not exist");
        }

        boolean rOffline = this.checkDeviceOffline(r);
        if (rOffline) {
            return ResultUtil.error("81100102", "Receiver offline", r.getPeerId());
        }

        return ResultUtil.success();
    }

    /**
     * 将要sourceId是否在webR中
     * @param rid
     * @param sourceId
     * @return
     */
    private boolean checkSourceExistInWebR(String rid, String sourceId) {
        try {
            List<Device> devicesFromWebR = deviceService.getExtFromWebR(rid);
            if (!CollectionUtils.isEmpty(devicesFromWebR)) {
                long count = devicesFromWebR.stream()
                        .filter(s -> StringUtils.equalsIgnoreCase(s.getPeerId(), sourceId))
                        .count();
                return count > 0;
            }
        } catch (Exception e) {
            log.error("startLive111>>>>>startLive exception,sourceId:[{}],rid:[{}],e:[{}]", sourceId, rid, e);
        }
        return false;
    }

    @Override
    public Result<String> startLiveExtendSource(String userId, String userRole, String rid, String sourceId,String type) {
        // 只有普通用户才判断
        if(StringUtils.equals(userRole, LocalConstant.UserRole.USER)){
            // 检查是否有startLive权限
            // checkFeature方法没有校验admin默认拥有的方法  暂时不check startLive feature
            boolean allow = userFeignService.checkUserRole(userId, "startLive");
            if (!allow) {
                return ResultUtil.userRoleNoFeature();
            }
        }
        Device r = deviceService.getCurrentDevice(rid);
        Device source = deviceService.getCurrentDevice(sourceId);
        if(source==null){
            //查询是否是Glink
        }

        // 校验设备 是否存在，状态是否正确
        Result<String> checkStatus = this.startLiveCheckStatusExtendSource(r);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        // 校验 R 是否存在 booking
        checkStatus = this.startLiveCheckBooking(rid);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

//        if (!enableCustomizedCC) {
//            // 如果是正式 CC 校验 Source/R 是否属于用户  以及是否调用 Grid CC 直播
//            BelongUserResult sourceBelongUser = this.sourceBelongUser(userId, source, rid);
//
//            if (sourceBelongUser.getCode() == BelongUserResult.NOT_BELONG) {
//                return ResultUtil.error("81100110", "Source not belong to user", sourceId);
//            }
//
//            BelongUserResult rBelongUser = this.receiverBelongUser(userId, r);
//
//            if (rBelongUser.getCode() == BelongUserResult.NOT_BELONG) {
//                return ResultUtil.error("81100111", "Receiver not belong to user", rid);
//            }
//
//            // 如果是从Grid 请求过来的还要看有没有配对过，
//            // 如果之前有配对就不调 Grid 的 start Live
//            // 如果之前没有配对就调
//            if (sourceBelongUser.getCode() == BelongUserResult.GRID_BELONG) {
//
//                try {
//                    GridStartLiveParam param = new GridStartLiveParam()
//                            .setRequestId((String) sourceBelongUser.getResult()) // 获取到的 request id
//                            .setRId(rid)
//                            .setXId(sourceId)
//                            .setUserId(userId);
//
//                    Result result = gridFeignService.gridStartLive(param);
//
//                    if (StringUtils.equals(ResultUtil.SUCCESS, result.getErrorCode())) {
//                        return ResultUtil.success();
//                    } else {
//                        return ResultUtil.error("81100114", result.getErrorInfo());
//                    }
//
//                } catch (Exception e) {
//                    log.error("Grid start live failed :", e);
//                    return ResultUtil.error("81100113", "Grid start live failed :" + e.getMessage());
//                }
//            }
//        }

        // 下发 Ext 到 R
//        startLiveDistributeExt(rid, source);

        return this.startLiveCommand(rid, sourceId);
    }

    private boolean checkDeviceOffline(Device device) {
        if (device == null) {
            return true;
        }
        long start = System.currentTimeMillis();
        String status = device.getStatus();
        while (true) {
            if (!StringUtils.equals(status, LocalConstant.DeviceStatus.OFFLINE)) {
                // 如果不是 offline，直接返回
                return false;
            }
            if (System.currentTimeMillis() - start > liveCheckDeviceOfflineTime) {
                // 超过阈值，直接返回
                log.error("checkDeviceOffline up to threshold device offline peerId:{}", device.getPeerId());
                return true;
            }
            device = deviceService.getCurrentDevice(device.getPeerId());
            if (device == null) {
                // device 不存在，直接返回
                log.error("checkDeviceOffline device not exist peerId:{}");
                return true;
            }
            status = device.getStatus();
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                log.error(e.toString(), e);
            }
        }
    }


    private Result<String> startLiveCheckStatus(Device r, Device source){
        if (r == null) {
            return ResultUtil.error("81100101", "Receiver not exist");
        }

        boolean rOffline = this.checkDeviceOffline(r);
        if (rOffline) {
            return ResultUtil.error("81100102", "Receiver offline", r.getPeerId());
        }

        if (source == null) {
            return ResultUtil.error("81100103", "Source not exist");
        }
        if (!LocalConstant.DeviceType.T.equalsIgnoreCase(source.getType())) {
            boolean sourceOffline = this.checkDeviceOffline(source);
            if (sourceOffline) {
                return ResultUtil.error("81100104", "Source offline", source.getPeerId());
            }
        }
        if (LocalConstant.DeviceType.T.equalsIgnoreCase(source.getType()) && LocalConstant.DeviceStatus.LIVING.equalsIgnoreCase(source.getStatus())) {
            return ResultUtil.error("81100105", "Source living", source);
        }
        return ResultUtil.success();
    }
    private Result<String> startLiveCheckStatusExtendSource(Device r){
        if (r == null) {
            return ResultUtil.error("81100101", "Receiver not exist");
        }

        boolean rOffline = this.checkDeviceOffline(r);
        if (rOffline) {
            return ResultUtil.error("81100102", "Receiver offline", r.getPeerId());
        }

        return ResultUtil.success();
    }

    private Result<String> startLiveDistributeExt(String rid, Device source){
        // startLive对象是Ext，需要下发配对关系到Receiver
        String[] extTypes = extType.split(",");
        for (String type : extTypes) {
            if (StringUtils.equalsIgnoreCase(type, source.getType())) {
                String sourceId = source.getPeerId();
                extService.addExtToReceiver(rid, sourceId);
            }
        }
        return ResultUtil.success();
    }

    private Result<String> startLiveCheckBooking(String rid){
        boolean receiverRunningInBooking = this.receiverRunningInBooking(rid);
        if (receiverRunningInBooking) {
            return ResultUtil.error("81100112", "Receiver running in booking");
        }
        return ResultUtil.success();
    }



    private Result<String> startLiveCommand(String rid, String sourceId) {
        String data = RCommandDataUtil.startStopLive(sourceId);
        Result<String> startLiveResult = command(rid, CommandConstant.START_LIVE, data);
        return ReceiverResultUtil.startLiveResult(startLiveResult);
    }


    @Override
    public Result<String> stopLive(String userId, String userRole, String rid) {
        // 只有普通用户才判断
        if(StringUtils.equals(userRole, LocalConstant.UserRole.USER)) {
            // 检查是否有stopLive权限
            //checkFeature方法没有校验admin默认拥有的方法  暂时不check stopLive feature
            boolean allow = userFeignService.userHasFeature(userId, "stopLive");
            if (!allow) {
                return ResultUtil.userRoleNoFeature();
            }
        }
        Device r = deviceService.getCurrentDevice(rid);

        // Check R 状态
        Result<String> checkStatus = this.stopLiveCheckStatus(r);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        // 校验 R 是否存在 booking
        Result<String> bookingCheckStatus = this.stopLiveCheckBooking(rid);
        if (!bookingCheckStatus.assertSuccess()) {
            return bookingCheckStatus;
        }

        String sourceId = checkStatus.getResult();

        if (StringUtils.isBlank(sourceId)) {
            sourceId = r.getLivePeerId();
        }

        Device source = deviceService.getCurrentDevice(sourceId);

        // source 为 null,可能播放的本地源,库中和memcache中都查询不到
        // 直接调用stop 的方法
        // 如果 source 的 type 是 Rtil 则不需要check
        if(source != null
        && !StringUtils.equalsIgnoreCase(source.getType(),"Rtil") ) {

            if (!enableCustomizedCC) {
                // 如果是正式 CC 校验 Source/R 是否属于用户  以及是否调用 Grid CC 直播

                BelongUserResult sourceBelongUser = this.sourceBelongUser(userId, source, rid);

                if (sourceBelongUser.getCode() == BelongUserResult.NOT_BELONG) {
                    boolean isPartyLinePair = this.checkIsPartyLinePair(rid, sourceId);
                    if (!isPartyLinePair) {
                        return ResultUtil.error("81100110", "Source not belong to user");
                    } else {
                        log.error("stop check source not belong to user but is partyline pair, rid:[{}] sid:[{}]", rid, sourceId);
                    }
                }

                BelongUserResult rBelongUser = this.receiverBelongUser(userId, r);

                if (rBelongUser.getCode() == BelongUserResult.NOT_BELONG) {
                    return ResultUtil.error("81100111", "Receiver not belong to user");
                }


                if (sourceBelongUser.getCode() == BelongUserResult.GRID_BELONG || sourceBelongUser.getCode() == BelongUserResult.GRID_LOCAL_PAIRED_BELONG) {

                    GridStopLiveParam param = new GridStopLiveParam()
                            .setRId(rid)
                            .setXId(sourceId);
                    try {
                        Result result = gridFeignService.gridStopLive(param);

                        if (StringUtils.equals(ResultUtil.SUCCESS, result.getErrorCode())) {
                            return ResultUtil.success();
                        } else {
                            log.error("Grid stop live failed 1: ", result.getErrorInfo());
                        }
                    } catch (Exception e) {
                        log.error("Grid stop live failed 2:", e);
                    }
                    log.error("Try to stop live use local server.....");
                }
            }
        }

        return this.stopLiveCommand(rid, sourceId);
    }

    private Result<String> stopLiveCheckStatus(Device r){
        if (r == null) {
            return ResultUtil.error("81100201", "Receiver not exist");
        }
        String rid = r.getPeerId();
        if (LocalConstant.DeviceStatus.OFFLINE.equalsIgnoreCase(r.getStatus())) {
            return ResultUtil.error("81100202", "Receiver offline");
        }
        String sourceId = null;
        if (LocalConstant.DeviceStatus.ONLINE.equalsIgnoreCase(r.getStatus())) {
            // StopLive 时，R online 但是 workModel = 1，此时返回 sourceId
            sourceId = this.stopLiveCheckReceiverOnlineWorkModel1(rid);
            if (StringUtils.isBlank(sourceId)) {
                return ResultUtil.error("81100203", "Receiver online");
            }
        }

        if (StringUtils.isBlank(sourceId)) {
            sourceId = r.getLivePeerId();
        }

        return ResultUtil.success(sourceId);
    }

    private Result<String> stopLiveCheckBooking(String rid){
        boolean receiverRunningInBooking = this.receiverRunningInBooking(rid);
        if (receiverRunningInBooking) {
            return ResultUtil.error("81100112", "Receiver running in booking");
        }
        return ResultUtil.success();
    }

    private Result<String> stopLiveCommand(String rid, String sourceId) {
        String data = RCommandDataUtil.startStopLive(sourceId);
        Result<String> stopLiveResult = command(rid, CommandConstant.STOP_LIVE, data);
        return ReceiverResultUtil.stopLiveResult(stopLiveResult);
    }

    @Override
    public Result<String> startLiveForAPI(String rid, String sourceId) {
        Device r = deviceService.getCurrentDevice(rid);
        Device source = deviceService.getCurrentDevice(sourceId);
        Result<String> checkStatus = this.startLiveCheckStatus(r, source);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        checkStatus = this.startLiveCheckBooking(rid);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        // 下发 Ext 到 R
        startLiveDistributeExt(rid, source);

        return this.startLiveCommand(rid, sourceId);
    }

    @Override
    public Result<String> stopLiveForAPI(String rid, String sourceId) {
        Device r = deviceService.getCurrentDevice(rid);

        // 检查 R 状态
        Result<String> checkStatus = this.stopLiveCheckStatus(r);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        // 检查 R 是否存在 Booking
        checkStatus = this.stopLiveCheckBooking(rid);
        if (!checkStatus.assertSuccess()) {
            return checkStatus;
        }

        if (StringUtils.isEmpty(sourceId)) {
            // 获取 SourceId
            sourceId = checkStatus.getResult();

            if (StringUtils.isBlank(sourceId)) {
                sourceId = r.getLivePeerId();
            }
        }
        if (StringUtils.isEmpty(sourceId)) {
            return ResultUtil.error("81100207", "Can not get source");
        }
        return this.stopLiveCommand(rid, sourceId);
    }


    @Override
    public Result<String> setBitrateAndDelay(SetBitrateAndDelayParam param) {
        Device r = deviceService.getCurrentDevice(param.getRid());
        if (r == null) {
            return ResultUtil.error("81100301", "Receiver not exist");
        }
        if (LocalConstant.DeviceStatus.OFFLINE.equalsIgnoreCase(r.getStatus())) {
            return ResultUtil.error("81100302", "Receiver offline");
        }
        String data = RCommandDataUtil.setBitrateAndDelay(param);
        return command(param.getRid(), CommandConstant.SET_BITRATE_AND_DELAY, data);
    }

    @Override
    public Result<String> command(String rid, CommandConstant operate, String data) {
        CommandParam commandParam = new CommandParam(rid, operate.getCategoryId(), operate.getOperationType(), data);
        return rwsFeignService.command(commandParam);
    }



//    @Override
//    public Result<String> sendCommandToReceiver(String rId, CommandConstant command, String data){
//        CommandParam commandParam = new CommandParam(rId, command.getCategoryId(), command.getOperationType(), data);
//        return rwsFeignService.command(commandParam);
//    }


    /**
     * Source 是否属于当前用户
     * 1.如果是 Grid 需要
     *  a.是否 Grid token 配对过来
     *  b.是否 Grid request 配对过来 需要到 grid 中去 check
     * 2.anywhere 和 T 都有可能通过 token 配对过来
     * 3.在 user device 表中有记录
     *
     * @param userId 用户id
     * @param source  source 设备的信息
     * @param rid  r 的id
     * @return {@link BelongUserResult} 根据不同的来源返回不同Code
     * 方便后面的逻辑判断
     */
    private BelongUserResult sourceBelongUser(String userId, Device source,String rid) {

        // 如果是X需要额外的判断
        if (StringUtils.equals(LocalConstant.DeviceType.X, source.getType())) {

            // 是否是Token配对过来的
            List<String> list = userDeviceMapper.listUserTokenGridIds(userId, null);
            if (!CollectionUtils.isEmpty(list) && list.contains(source.getPeerId())) {
                return BelongUserResult.tokenGridBelong();
            }

            int count = myDeviceMapper.countUserDevice(userId, source.getPeerId());

            // 如果这个 Grid 是直接在这个账户下的还需要看是否配对，配对了才可以 live
            if (count > 0) {
                try {
                    List<String> xPairedRids = devicePairService.listCacheXPairR(source.getPeerId());
                    if (!CollectionUtils.isEmpty(xPairedRids)) {
                        for (String xPairedRid : xPairedRids) {
                            if (StringUtils.equalsIgnoreCase(xPairedRid, rid)) {
                                return BelongUserResult.gridLocalPairdBelong();
                            }
                        }
                    }
                } catch (IOException e) {
                    log.error("Grid sourceBelongUser listXPairR error userId [{}] , peerId [{}], livePeerId [{}]",
                            userId, source.getPeerId(), source.getPeerId(), e);
                }
            }

            // 以及从 Grid 获取到的requestId start Live 的时候需要用到
            try {
                List<AcceptedGrid> gridRequestList = gridFeignService.getGridByUserId(userId, source.getPeerId());

                if (!CollectionUtils.isEmpty(gridRequestList)) {
                    for (AcceptedGrid acceptedGrid : gridRequestList) {
                        if (StringUtils.equalsIgnoreCase(acceptedGrid.getPeerId(), source.getPeerId())) {
                            return BelongUserResult.gridBelong(acceptedGrid.getRequestId());
                        }
                    }
                }
            } catch (Exception e) {
                log.error("getGridByUserId error userId [{}], peerId [{}] ,livePeerId",
                        userId, source.getPeerId(), source.getLivePeerId(), e);
            }

            // 是 Grid 但是以上的情况都不存在
            return BelongUserResult.notBelong();
        }

        int count = myDeviceMapper.countUserDevice(userId, source.getPeerId());

        if (count > 0) {
            return BelongUserResult.localBelong();
        }

        Set<String> rids = new HashSet<>();
        rids.add(rid);
        Set<String> sids = tokenFeignService.listRsPairedTids(rids);
        if (!CollectionUtils.isEmpty(sids)) {
            for (String sid : sids) {
                if (StringUtils.equalsIgnoreCase(sid, source.getPeerId())) {
                    return BelongUserResult.tokenBelong();
                }
            }
        }

        return BelongUserResult.notBelong();
    }



    private BelongUserResult getBelongUserResult(String userId, Device source) {
        int count = myDeviceMapper.countUserDevice(userId, source.getPeerId());

        if (count > 0) {
            return BelongUserResult.localBelong();
        }

        count = myDeviceMapper.sourceFromUserToken(userId, source.getPeerId());
        if (count > 0) {
            return BelongUserResult.tokenBelong();
        }

        return BelongUserResult.notBelong();
    }

    /**
     * R 是否属于当前用户
     * 1.在 user device 表中有记录
     *
     * @param userId 用户id
     * @param receiver R 设备的信息
     * @return {@link BelongUserResult} 根据不同的来源返回不同Code
     * 方便后面的逻辑判断
     */
    private BelongUserResult receiverBelongUser(String userId, Device receiver) {
        return getBelongUserResult(userId, receiver);
    }


    private boolean receiverRunningInBooking(String rid) {
        int count = myDeviceMapper.receiverRunningInBooking(rid, System.currentTimeMillis());
        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * StopLive 时，R online 但是 workModel = 1，此时返回 sourceId
     * @param rid
     * @return
     */
    private String stopLiveCheckReceiverOnlineWorkModel1(String rid){
        CommandParam commandParam = new CommandParam(rid, CommandConstant.QUERY_KERNEL_STATE.getCategoryId(), CommandConstant.QUERY_KERNEL_STATE.getOperationType(), null);
        commandParam.setTimeout(10000L);
        Result<String> queryKernelResult =  rwsFeignService.command(commandParam);
        if (!queryKernelResult.assertSuccess()) {
            log.error("StopLive R online queryKernel failed result:[{}]", queryKernelResult);
            return null;
        }
        String result = queryKernelResult.getResult();
        if (StringUtils.isBlank(result)) {
            log.error("StopLive R online queryKernel return null result:[{}]", result);
            return null;
        }

        try {
            JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
            int workMode = jsonNode.get("WorkMode").asInt();
            if (workMode != 1) {
                log.error("StopLive R online queryKernel workModel:[{}] can not stop result:[{}]", workMode, result);
                return null;
            }
            String currentTStrId = jsonNode.get("CurrentTStrIdHex").asText().toLowerCase();
            if (StringUtils.isBlank(currentTStrId)) {
                log.error("StopLive R online queryKernel workModel:[{}] currentTStrId null:[{}] can not stop result:[{}]", workMode, currentTStrId, result);
                return null;
            }
            log.error("StopLive R online queryKernel workModel:[{}] currentTStrId :[{}] can stop result:[{}]", workMode, currentTStrId, result);
            return currentTStrId.toLowerCase();
        } catch (IOException e) {
            log.error(e.toString(), e);
            log.error("StopLive R online queryKernel error result:[{}]", result);
            return null;
        }
    }
    @Override
    public Result<String> addGLink(String userId, GLinkParam gLinkParam) throws Exception{
        if(StringUtils.isEmpty(gLinkParam.getName())|| StringUtils.isEmpty(gLinkParam.getUrl()) ||StringUtils.isEmpty(gLinkParam.getType()) ){
            return ResultUtil.paramError();
        }
        //检验名称是否存在，存在不能添加
        int exist = extendExternalMapper.countByName(gLinkParam.getName());
        if(exist>0){//用户名已存在
            return ResultUtil.error("20100010","Name exist");
        }
        try {
            //校验webR中的GLink是否重复
            List<ExtendExternal> gLinkFromWebR = deviceService.getGLinkFromWebR(gLinkParam.getRid());
            if (!CollectionUtils.isEmpty(gLinkFromWebR)) {
                List<ExtendExternal> collect = gLinkFromWebR.stream().filter(s -> StringUtils.equals(s.getName(), gLinkParam.getName())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(collect)) {
                    return ResultUtil.error("20100010","Name exist in webR");
                }
            }
        } catch (Exception e) {
            log.error("addGLink>>>>>>param:[{}],exception:[{}]", gLinkParam, e);
        }
        //发给R
        Map glinkMap = new HashMap();
        glinkMap.put("Name",gLinkParam.getName());
        glinkMap.put("Url",gLinkParam.getUrl());
        glinkMap.put("Type",gLinkParam.getType());
        String params = MyUtil.MAPPER.writeValueAsString(glinkMap);
        Result<String> addGlinkResult = command(gLinkParam.getRid(),CommandConstant.ADD_GLINK,params);
        //本地入库
        if("0x0".equals(addGlinkResult.getErrorCode())){
            ExtendExternal extendExternal = new ExtendExternal();
            extendExternal.setId(distributedGlobalIdUtil.netxId()+"");
            extendExternal.setName(gLinkParam.getName());
            extendExternal.setUrl(gLinkParam.getUrl());
            extendExternal.setType(gLinkParam.getType());
            extendExternal.setCreateTime(System.currentTimeMillis());
            extendExternal.setPeerId(addGlinkResult.getResult());
            extendExternal.setDeleteFlag(0);
            extendExternal.setRid(gLinkParam.getRid());
            extendExternalMapper.insert(extendExternal);
            //创建R关系
            ExternalReceiverRelation externalReceiverRelation = new ExternalReceiverRelation();
            externalReceiverRelation.setId(distributedGlobalIdUtil.netxId()+"");
            externalReceiverRelation.setRId(gLinkParam.getRid());
            externalReceiverRelation.setFullId(addGlinkResult.getResult());
            externalReceiverRelationMapper.insert(externalReceiverRelation);
        }
        return addGlinkResult;
    }

    @Override
    public Result<String> editGLink(String userId, GLinkParam gLinkParam) throws Exception{
    //检验名称是否存在，存在不能添加
        List<ExtendExternal> extendExternalList = extendExternalMapper.selectByName(gLinkParam.getName());
        if(extendExternalList.size()>0 && !gLinkParam.getPeerId().equals(extendExternalList.get(0).getPeerId())){//用户名已存在
            return ResultUtil.error("20100010","Name exist");
        }
        //校验webR中的GLink是否重复
        try {
            List<ExtendExternal> gLinkFromWebR = deviceService.getGLinkFromWebR(gLinkParam.getRid());
            if (!CollectionUtils.isEmpty(gLinkFromWebR)) {
                List<ExtendExternal> collect = gLinkFromWebR.stream().filter(s -> StringUtils.equals(s.getName(), gLinkParam.getName())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(collect) && !StringUtils.equalsIgnoreCase(collect.get(0).getPeerId(), gLinkParam.getPeerId())) {
                    return ResultUtil.error("20100010", "Name exist in webR");
                }
            }
        } catch (Exception e) {
            log.error("editGLink>>>>>>param:[{}],exception:[{}]", gLinkParam, e);
        }
        //发给R
        Map glinkMap = new HashMap();
        String peerId = gLinkParam.getPeerId();
        String id = peerId.substring(0,16);
        String reSourceId = peerId.substring(16);
        glinkMap.put("Id",id);
        glinkMap.put("ResourceId",reSourceId);
        glinkMap.put("Name",gLinkParam.getName());
        glinkMap.put("Url",gLinkParam.getUrl());
        String params = MyUtil.MAPPER.writeValueAsString(glinkMap);
        Result<String> addGlinkResult = command(gLinkParam.getRid(),CommandConstant.EDIT_GLINK,params);
        //修改本地数据库
        if("0x0".equals(addGlinkResult.getErrorCode())){
            ExtendExternal extendExternal = new ExtendExternal();
            extendExternal.setName(gLinkParam.getName());
            extendExternal.setUrl(gLinkParam.getUrl());
            extendExternal.setUpdateTime(System.currentTimeMillis());
            extendExternal.setPeerId(gLinkParam.getPeerId());
            extendExternalMapper.updateExtendExternal(extendExternal);
        }
        return addGlinkResult;
    }

    @Override
    public Result<String> deleteGLink(String userId, GLinkParam gLinkParam) throws Exception{
        Map glinkMap = new HashMap();
        String peerId = gLinkParam.getPeerId();
        glinkMap.put("IdHex",peerId);
        String params = MyUtil.MAPPER.writeValueAsString(glinkMap);
        Result<String> addGlinkResult = command(gLinkParam.getRid(),CommandConstant.DELETE_GLINK,params);
        //修改本地数据库
        if("0x0".equals(addGlinkResult.getErrorCode())){
            ExtendExternal extendExternal = new ExtendExternal();
//            extendExternal.setName(gLinkParam.getName());
//            extendExternal.setUrl(gLinkParam.getUrl());
//            extendExternal.setUpdateTime(System.currentTimeMillis());
            extendExternal.setPeerId(peerId);
            extendExternal.setDeleteFlag(1);
            extendExternalMapper.updateExtendExternal(extendExternal);
        }
        return addGlinkResult;
    }

    @Override
    public Result<String> getModuleInfo(String userId, String rid, String params) {
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> moduleInfo = command(rid,CommandConstant.GET_MODULE_INFO,params);
        return moduleInfo;
    }

    @Override
    public Result<String> getCoreInfo(String userId, String rid, String params) {
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> coreInfo = command(rid,CommandConstant.GET_CORE_INFOS,params);
        return coreInfo;
    }

    @Override
    public Result<String> getAllStatus(String userId, String rid, String params) {
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> allstatus = command(rid,CommandConstant.GET_ALL_STATUS,params);
        return allstatus;
    }

    @Override
    public Result<String> switchCodec(String userId, SwitchCodeParam switchCodeParam) {
        String params = "";
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
//        map.put("Data", "{\"EncoderName\":"+switchCodeParam.getEncoderName()+",\"CodecStr\":"+switchCodeParam.getCodecStr()+"}");
        map.put("EncoderName", switchCodeParam.getEncoderName());
        map.put("CodecStr", switchCodeParam.getCodecStr());
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> allStatus = command(switchCodeParam.getRid(),CommandConstant.SWITCH_CODE_C,params);
        return allStatus;
    }

    @Override
    public Result<String> switchPackEncoderSource(String userId, SwitchPackEncoderSourceParam switchPackEncoderSourceParam) {
        String params="";
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        map.put("LiveOverrideFlag", switchPackEncoderSourceParam.getLiveOverrideFlag());
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> allStatus = command(switchPackEncoderSourceParam.getRid(),CommandConstant.SWITCH_PACK_ENCODER_SOURCE,params);
        return allStatus;
    }

    @Override
    public Result<String> getCommandConfig(String userId, String rid, String params) {
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> commandConfig = command(rid,CommandConstant.GET_COMMAND_CONFIG,params);
        return commandConfig;
    }

    @Override
    public Result<String> updateCommandConfig(String userId, UpdateCommandConfigParam updateCommandConfigParam) {
        String params = "";
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
//        map.put("Data", "{\"Bitrate1\":"+updateCommandConfigParam.getBitrateOne()+",\"Bitrate2\":"+updateCommandConfigParam.getBitrateTwo()+",\"Port1\":"+updateCommandConfigParam.getPortOne()+",\"Port2\":"+updateCommandConfigParam.getPortTwo()+"}");
        map.put("Bitrate1", updateCommandConfigParam.getBitrateOne());
        map.put("Bitrate2", updateCommandConfigParam.getBitrateTwo());
        map.put("Port1", updateCommandConfigParam.getPortOne());
        map.put("Port2", updateCommandConfigParam.getPortTwo());
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> commandConfig = command(updateCommandConfigParam.getRid(),CommandConstant.UPDATE_COMMAND_CONFIG,params);
        return commandConfig;
    }


    @Override
    public Result<String> getBitrateRange(String userId, String rid, String params) {
        Map map = new HashMap();
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> bitrateRange = command(rid,CommandConstant.GET_BITRATE_RANGE,params);
        return bitrateRange;
    }

    @Override
    public Result<String> queryConfig(String userId, String rid) {
        String params="";
        String [] ridArr =  rid.split(",");
        Map<String,Object> resultMap = new HashMap<>();
        for (String peerId:ridArr){
            Map map = new HashMap();
            map.put("ClientRequestId", UUID.randomUUID());
            map.put("ContentType", "");
//            map.put("Data", "{\"CategoryName\":\"Encoder\",\"ShortName\":\"WebREncoder\",\"PropertyName\":\"SDICardNumber\"}");
            map.put("CategoryName", "Encoder");
            map.put("ShortName", "WebREncoder");
            map.put("PropertyName", "SDICardNumber");
            try {
                params = MyUtil.MAPPER.writeValueAsString(map);
            } catch (JsonProcessingException e) {
                log.error("msg:{},e:{}",e.getMessage(),e);
            }
            try {
                Result<String> config = command(peerId,CommandConstant.QUERY_SDIIN_CONFIG,params);
                log.error("Result<String> config=="+config.getResult());

                if(config.getResult() !=null &&config.getResult().contains("Nodevalue")){
//                    String [] carArr = config.getResult().split("Nodevalue\":\"");
//                    String carNum = carArr[1].substring(0,1);
                    JSONObject s = JSONObject.parseObject(config.getResult());
                    String carNum =  s.get("Nodevalue").toString();
                    if(StringUtils.isEmpty(carNum)){
                        carNum="1";
                    }
                    resultMap.put(peerId,peerId.toUpperCase()+"SDI"+carNum);
                }else{
                    resultMap.put(peerId,peerId.toUpperCase()+"SDI1");
                }
            } catch (Exception e) {
                log.error("Result<String> config Exception",e);
                resultMap.put(peerId,peerId.toUpperCase()+"SDI1");
            }
        }

        return ResultUtil.success(resultMap);
    }

    @Override
    public Result<String> switchArea(String userId, SwitchAreaParam switchAreaParam) {
        String params="";
        Map map = new HashMap();
//        map.put("OperationType", "103");
//        map.put("CategoryId", "2152866561");
//        map.put("OperationType", "103");
//        map.put("Data", "{\"Label\":\""+switchAreaParam.getLabel()+"\"}");
        map.put("Label", "\""+switchAreaParam.getLabel()+"\"");
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        Result<String> switchArea = command(switchAreaParam.getRid(),CommandConstant.SWITCH_AREA,params);
        return switchArea;
    }

    @Override
    public Result<String> coreInfo(String userId, SwitchAreaParam switchAreaParam) {
        Result<String> coreInfo = command(switchAreaParam.getRid(),CommandConstant.CORE_INFO,null);
        return coreInfo;
    }

    /**
     *
     * @param userId userId
     * @param switchAreaParam switchAreaParam
     * @return  Result
     */
    public Result<String> getLiveVoIP(String userId, SwitchAreaParam switchAreaParam) {
        String params="";
        Map map = new HashMap();
        map.put("ShortName", "PluginCompatibility");
        map.put("CategoryName", "Core.Macro");
        map.put("PropertyName", "BindVoIPWithLive");
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("params Error",e);
        }
//        map.put("Data", "{\"Label\":\""+switchAreaParam.getLabel()+"\"}");
        Result<String> getLiveVoIP = command(switchAreaParam.getRid(),CommandConstant.GET_LIVE_VOIP,params);
        return getLiveVoIP;
    }

    @Override
    public Result<String> getVoipVolume(String userId, VoipVolumeParam voipVolumeParam) {
        Result<String> getVoipVolume ;
        try {
            String params="";
            Map map = new HashMap();
            map.put("ClientRequestId", UUID.randomUUID());
            map.put("ContentType", "");
            try {
                params = MyUtil.MAPPER.writeValueAsString(map);
            } catch (JsonProcessingException e) {
                log.error("params Error",e);
            }
//        map.put("Data", "{\"Label\":\""+switchAreaParam.getLabel()+"\"}");
            getVoipVolume = command(voipVolumeParam.getRid(), CommandConstant.VOIP_VOLUME,params);
        } catch (Exception e) {
            log.error("=getVoipVolume=",e);
            getVoipVolume = new Result<>();
        }
        return getVoipVolume;
    }

    @Override
    public Result<String> getGridEncodeVideoUrl(String userId, VoipVolumeParam voipVolumeParam) {
            Result<String> gridEncodeVideoUrl ;
            try {
                String params="";
                Map map = new HashMap();
                map.put("ClientRequestId", UUID.randomUUID());
                map.put("Data", "");
                try {
                    params = MyUtil.MAPPER.writeValueAsString(map);
                } catch (JsonProcessingException e) {
                    log.error("params Error",e);
                }
//        map.put("Data", "{\"Label\":\""+switchAreaParam.getLabel()+"\"}");
                gridEncodeVideoUrl = command(voipVolumeParam.getRid(), CommandConstant.GRID_ENCODE_URL,params);
            } catch (Exception e) {
                log.error("=getVoipVolume=",e);
                gridEncodeVideoUrl = new Result<>();
            }
            return gridEncodeVideoUrl;
    }

    private boolean checkIsPartyLinePair(String rid, String sid) {
        try {
            if (sid.length() != 16) {
                return false;
            }
            Result<Object> objectResult = tokenFeignService.queryPairListByTRidAndType(rid, sid, partylineTokenType);
            Object result = objectResult.getResult();
            if (result == null) {
                return false;
            }
            int exist = ((ArrayList) result).size();
            return exist > 0;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     *
     * @param userId userId
     * @param liveVoipParam liveVoipParam
     * @return Result
     */
    public Result<String> setLiveVoIP(String userId, LiveVoipParam liveVoipParam) {
        String params="";
        Map map = new HashMap();
        map.put("ShortName", "PluginCompatibility");
        map.put("CategoryName", "Core.Macro");
        map.put("PropertyName", "BindVoIPWithLive");
        map.put("ClientRequestId", UUID.randomUUID());
        map.put("ContentType", "");
        map.put("Nodevalue", liveVoipParam.isNodevalue());
        try {
            params = MyUtil.MAPPER.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            log.error("params Error",e);
        }
        Result<String> setLiveVoIP = command(liveVoipParam.getRid(),CommandConstant.SET_LIVE_VOIP,params);
        return setLiveVoIP;
    }

    /**
     *
     * @param extendExternal extendExternal
     * @throws Exception 编译异常
     */
    public void updateExtentEernal(ExtendExternal extendExternal) throws Exception{
        myDeviceMapper.updateDeviceUrl(extendExternal);
    }

    @Override
    public Result command(String rid, CommandConstant operate) {
        CommandParam commandParam = new CommandParam(rid, operate.getCategoryId(), operate.getOperationType());
        return rwsFeignService.command(commandParam);
    }

    @Override
    public Result restartOrRebootLinuxR(String rid, CommandConstant operate) {
        //1.校验R的版本，只有7.7版本的R才可以重启机器
        Device device = deviceService.getCurrentDevice(rid);
        if (device == null) {
            throw new ServerException(ResultConstant.Device.DEVICE_NOT_EXIST);
        }
        if (!StringUtils.equalsIgnoreCase(device.getType(), LocalConstant.DeviceType.R)) {
            throw new ServerException(ResultConstant.Device.DEVICE_IS_NOT_R);
        }
        String version = device.getVersion();
        double receiverVersion = StringUtils.isNotEmpty(version) ? version.length() > 3
                ? Double.parseDouble(version.substring(0, 3)) : Double.parseDouble(version) : 0;
        if (receiverVersion < linuxRestartVersion) {
            throw new ServerException(ResultConstant.Device.RECEIVER_VERSION_MUST_BE_MORE_THAN_7_7);
        }
        return this.command(rid, operate);
    }

    @Override
    public Result ecoPreview(String rid, CommandConstant operate,String data) {
        CommandParam commandParam = new CommandParam(rid, operate.getCategoryId(), operate.getOperationType(),data);
        return rwsFeignService.command(commandParam);
    }

    @Override
    public Result getEcoPreviewInfo(String rid, CommandConstant operate) {
        CommandParam commandParam = new CommandParam(rid, operate.getCategoryId(), operate.getOperationType());
        return rwsFeignService.command(commandParam);
    }

    @Override
    public Result exitEcoPreviewInfo(String rid, CommandConstant exitEcoPreview) {
        CommandParam commandParam = new CommandParam(rid, exitEcoPreview.getCategoryId(), exitEcoPreview.getOperationType());
        return rwsFeignService.command(commandParam);
    }

    @Override
    public Result getEncoderLogo(String rid, CommandConstant operate, String data) {
        String categoryId = operate.getCategoryId();
        String operationType = operate.getOperationType();
        CommandParam commandParam = new CommandParam(rid, categoryId, operationType,data);
        return rwsFeignService.command(commandParam);
    }

    @Override
    public Result getVersionR(String peerId, CommandConstant operate) {
        String categoryId = operate.getCategoryId();
        String operationType = operate.getOperationType();
        CommandParam commandParam = new CommandParam(peerId, categoryId, operationType);
        return rwsFeignService.command(commandParam);
    }
    @Override
    public Result<String> gridAndReceiverSendMessageToSearch(String userId, SendSlugMessageParam param) {

        //如果是Grid，需要校验cc中的owner权限
     /*   boolean  isOwner = userFeignService.checkSourceIsOwnerByUserId(userId, param.getGridId());
        if (!isOwner) {
            log.error("createOrUpdateSlug>>>>owner is false, userId:[{}],tPeerId:[{}]", userId, param.getGridId());
            throw new ServerException(ResultConstant.Slug.SLUG_FAILED);
        }*/

        UpdateSlugParam updateSlugParam = new UpdateSlugParam();

        updateSlugParam.setSlug(param.getCondition())
                .setSourceId(param.getSourceId())
                .setSourceName(deviceService.getCurrentDevice(param.getSourceId()).getName())
                .setEndTime(param.getEndTime());
        if(StringUtils.isEmpty(param.getId())){
            updateSlugParam.setId( MyUtil.getUUID());
        }else {
            updateSlugParam.setId(param.getId());
        }

        this.updateSlug(updateSlugParam);

        return ResultUtil.success();
    }
    /**
     * 添加或者更新slug信息
     * @param param 参数
     */
    private void updateSlug(UpdateSlugParam param) {
        String url = this.updateSlugUrl;
        if (!StringUtils.startsWith(url, "http")) {
            url = "http://" + url;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = null;
        try {
            headers.add(LocalConstant.API_HEADER_PARAM_KEY, this.generatorAccess());
            httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);
        } catch (IOException e) {
            log.error("RPC TVU Search Service parse json exception url:{} pram:[{}]", url, param);
            throw new ServerException(ResultConstant.Slug.CREATE_SLUG_FAILED);
        }
        ResponseEntity<String> responseEntity;
        log.error("RPC TVU Search Service updateSlug url:{} pram:[{}]", url, param);
        try {
            responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error("RPC TVU Search Service updateSlug Http error url:{} pram:[{}]", url, param, e);
            throw new ServerException(ResultConstant.Slug.CREATE_SLUG_FAILED);
        }
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.error("RPC TVU Search Service updateSlug not 200 url:{} pram:[{}] responseEntity:[{}]", url, param, responseEntity);
            throw new ServerException(ResultConstant.Slug.CREATE_SLUG_FAILED);
        }
    }


 /*   @Override
    public Result<String> deleteGridSlug(String userId, SendSlugMessageParam param) {
        //如果是Grid，需要校验cc中的owner权限
        boolean  isOwner = userFeignService.checkSourceIsOwnerByUserId(userId, param.getGridId());
        if (!isOwner) {
            log.error("createOrUpdateSlug>>>>owner is false, userId:[{}],tPeerId:[{}]", userId, param.getGridId());
            throw new ServerException(ResultConstant.Slug.SLUG_FAILED);
        }
        this.deleteSlug(param.getId());
        return ResultUtil.success();
    }*/

    private String generatorAccess() throws IOException {
        String requestId = MyUtil.getUUID();
        String appKey = accessProperties.getAppKey();
        String appSecret = accessProperties.getAppSecret();
        String timestamp = getAccessTimestamp();
        String signature = EndecryptUtil.MD5(appSecret + timestamp);

        return JsonUtil.toJsonStr(new AccessParam()
                .setAppkey(appKey)
                .setTimestamp(timestamp)
                .setSignature(signature)
                .setRequestId(requestId));
    }
    private String getAccessTimestamp() {
        Result timestamp = accessFeignService.getTime();
        return timestamp.getResult() + "";
    }

    @Override
    public Result<String> getSlugByGridId(String sourceId) throws Exception {
        List<String> list = new ArrayList<>();
        list.add(sourceId);
        String str = JsonUtil.toJsonStr(list);
      //  List<SlugInfo> slugInfos = tvuSearchFeignService.newestSlugInfo(list);
        String url = this.getSlugUrl;
        if (!StringUtils.startsWith(url, "http")) {
            url = "http://" + url;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = null;
        try {
            headers.add(LocalConstant.API_HEADER_PARAM_KEY, this.generatorAccess());
            httpEntity = new HttpEntity(str, headers);
        } catch (IOException e) {
            log.error(" TVU Search Service parse json exception url:{} pram:[{}]", url, str);
            throw new ServerException(ResultConstant.Slug.SELECT_SLUG_FAILED);
        }
        ResponseEntity<String> responseEntity;
        log.error(" TVU Search Service getSlug url:{} str:[{}]", url, str);
        try {
            responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error(" TVU Search Service getSlug Http error str:{} pram:[{}]", url, str, e);
            throw new ServerException(ResultConstant.Slug.SELECT_SLUG_FAILED);
        }
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.error(" TVU Search Service getSlug not 200 url:{} str:[{}] responseEntity:[{}]", url, str, responseEntity);
            throw new ServerException(ResultConstant.Slug.SELECT_SLUG_FAILED);
        }
        JSONObject jsonRes = JSON.parseObject(responseEntity.getBody());
        Object result = jsonRes.get("result");
        return ResultUtil.success(result);
    }

   /* *//**
     * 删除slug信息
     * @param externalId 参数
     *//*
    public void deleteSlug(String externalId) {
        String deleteUrl = this.deleteSlugUrl;
        if (!StringUtils.startsWith(deleteUrl, "http")) {
            deleteUrl = "http://" + deleteUrl;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = null;
        Map param = new HashMap();
        param.put("externalId", externalId);
        try {
            headers.add(LocalConstant.API_HEADER_PARAM_KEY, this.generatorAccess());
            httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);
        } catch (IOException e) {
            log.error("RPC TVU Search Service delete slug parse json exception url:{} pram:[{}]", deleteUrl, param);
            throw new ServerException(ResultConstant.Slug.DELETE_SLUG_FAILED);
        }
        ResponseEntity<String> responseEntity;
        log.error("RPC TVU Search Service deleteSlug url:{} pram:[{}]", deleteUrl, param);
        try {
            responseEntity = restTemplate.postForEntity(deleteUrl, httpEntity, String.class);
        } catch (RestClientException e) {
            log.error("RPC TVU Search Service deleteSlug Http error url:{} pram:[{}]", deleteUrl, param, e);
            throw new ServerException(ResultConstant.Slug.DELETE_SLUG_FAILED);
        }
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            log.error("RPC TVU Search Service deleteSlug not 200 url:{} pram:[{}] responseEntity:[{}]", deleteUrl, param, responseEntity);
            throw new ServerException(ResultConstant.Slug.DELETE_SLUG_FAILED);
        }
    }*/
}
